package com.t.bricks.bussiness.controller.filecabinet;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

import java.time.LocalDateTime;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.t.bricks.bussiness.db.entity.filecabinet.FileCabinet;
import com.t.bricks.bussiness.service.filecabinet.FileCabinetService;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.app.HttpServletUtil;
import com.t.bricks.utils.function.data.ValidDataUtil;

@RestController
@Api(value="文件柜", tags={"基本业务-文件柜操作接口"})
@RequestMapping("/file/cabinet/")
public class FileCabinetController {

	/**
	 * 加密用干扰串
	 */
	@Value("${disturb:888}")
	private String disturbStr;

	@Autowired
	private FileCabinetService fileCabinetService;

	/**
	 * 测试连接
	 * @return
	 */
	@ApiOperation(value="测试连接")
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 时间}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误")
	})
	@RequestMapping(method={RequestMethod.GET}, value="/time")
	public MsgEmity time() {
		return MsgEmity.success(LocalDateTime.now(), "连接成功");
	}

	/**
	 * 文件上传
	 * 注意:为内部请求,跳过请求验证
	 * @param file 文件
	 * @param person 操作人
	 * @param project 项目名
	 * @return
	 */
	@ApiOperation(value="文件上传", notes="将文件上传到配置中的目录下,注意:为内部请求")
	@ApiImplicitParams({
		@ApiImplicitParam(name="file", value="文件", dataType="__file", paramType="form", required=true),
		@ApiImplicitParam(name="person", value="操作人", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="project", value="项目名", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|文件记录编号}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="上传失败，文件不存在"),
		@ApiResponse(code=8002, message="文件转换异常！"),
		@ApiResponse(code=8003, message="保存记录失败！"),
		@ApiResponse(code=7001, message="新增文件信息记录未能得到预期影响值(预期1)！"),
		@ApiResponse(code=7002, message="新增文件信息记录时发生异常！"),
		@ApiResponse(code=7003, message="查询文件信息记录失败！"),
		@ApiResponse(code=7008, message="检查待修改内容是否存在重复数据发生异常！"),
		@ApiResponse(code=7101, message="重新上传时,查询文件信息记录失败！"),
		@ApiResponse(code=7103, message="重新上传时,查询文件信息记录发生异常！"),
		@ApiResponse(code=7201, message="重新上传时,修改文件信息记录失败！"),
		@ApiResponse(code=7202, message="重新上传时,修改文件信息记录发生异常！")
	})
	@RequestMapping(method=RequestMethod.POST, value="/up/inside")
	public MsgEmity upFile(@RequestParam("file") MultipartFile file,
			String person, String project) {
		return fileCabinetService.upFile(file, person, project);
	}

	/**
	 * 文件上传
	 * @param file 文件
	 * @param person 操作人
	 * @param project 项目名
	 * @param requestDate 请求时间
	 * @param checkKey 验证key
	 * @return
	 */
	@ApiOperation(value="文件上传", notes="将文件上传到配置中的目录下,保存的文件名为流水号名,返回保存的文件名;验证key由操作人、项目名、干扰串通过';'串联后进行MD5操作得到")
	@ApiImplicitParams({
		@ApiImplicitParam(name="file", value="文件", dataType="__file", paramType="form", required=true),
		@ApiImplicitParam(name="person", value="操作人", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="project", value="项目名", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="requestDate", value="请求时间", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="checkKey", value="验证key", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值|文件记录编号}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="上传失败，文件不存在"),
		@ApiResponse(code=8002, message="文件转换异常！"),
		@ApiResponse(code=8003, message="保存记录失败！"),
		@ApiResponse(code=7001, message="新增文件信息记录未能得到预期影响值(预期1)！"),
		@ApiResponse(code=7002, message="新增文件信息记录时发生异常！"),
		@ApiResponse(code=7003, message="查询文件信息记录失败！"),
		@ApiResponse(code=7008, message="检查待修改内容是否存在重复数据发生异常！"),
		@ApiResponse(code=7101, message="重新上传时,查询文件信息记录失败！"),
		@ApiResponse(code=7103, message="重新上传时,查询文件信息记录发生异常！"),
		@ApiResponse(code=7201, message="重新上传时,修改文件信息记录失败！"),
		@ApiResponse(code=7202, message="重新上传时,修改文件信息记录发生异常！")
	})
	@RequestMapping(method=RequestMethod.POST, value="/up")
	public MsgEmity upFile(@RequestParam("file") MultipartFile file,
			String person, String project, String requestDate, String checkKey) {
		return fileCabinetService.upFile(file, person, project, requestDate, checkKey);
	}

	/**
	 * 文件上传(自定义保存路径)
	 * @param file 文件
	 * @param person 操作人
	 * @param project 项目名
	 * @param customPath 自定义路径
	 * @param requestDate 请求时间
	 * @param checkKey 验证key
	 * @return
	 */
	@ApiOperation(value="文件上传(自定义保存路径)")
	@ApiImplicitParams({
		@ApiImplicitParam(name="file", value="文件", dataType="__file", paramType="form", required=true),
		@ApiImplicitParam(name="person", value="操作人", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="project", value="项目名", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="customPath", value="指定路径", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="requestDate", value="请求时间", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="checkKey", value="验证key", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method=RequestMethod.POST, value="/up/custom")
	public MsgEmity upFileCustom(@RequestParam("file") MultipartFile file,
			String person, String project, String customPath,
			String requestDate, String checkKey) {
		return fileCabinetService.upFileCustom(file, person, project, customPath, requestDate, checkKey);
	}

	/**
	 * 文件下载
	 * @param request
	 * @param response
	 * @param sId 记录编号
	 * @param requestDate 请求时间
	 * @param checkKey 验证key
	 */
	@ApiOperation(value="文件下载", notes="文件下载,为防止请求链接被截获然后反向操作,需要对每次请求进行验证加密串,请求操作存在过期")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sId", value="记录编号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="requestDate", value="请求时间(yyyy-MM-dd HH:mm:ss)", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="checkKey", value="验证密钥", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="成功下载到文件|{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=6001, message="待验证的密钥为空"),
		@ApiResponse(code=6002, message="请求时间不能为空"),
		@ApiResponse(code=6003, message="请求时间比服务器时间早，请校对两边系统时间"),
		@ApiResponse(code=6004, message="请求时间参数已经过期，请重新请求"),
		@ApiResponse(code=6005, message="验证密钥不一致"),
		@ApiResponse(code=8001, message="记录编号不能为空"),
		@ApiResponse(code=7101, message="文件信息数据不存在"),
		@ApiResponse(code=7103, message="文件信息查询失败，发生异常"),
		@ApiResponse(code=9001, message="文件信息记录中缺失文件路径")
	})
	@RequestMapping(method=RequestMethod.GET, value="/download")
	public void download(HttpServletRequest request, HttpServletResponse response,
			String sId, String requestDate, String checkKey) {
		//-- 验证请求是否合法 --//
		MsgEmity me = ValidDataUtil.checkQueryKey(checkKey, requestDate, disturbStr, sId);
		if (!me.isSuccess()) {
			HttpServletUtil.setTxt(response, me);
			return;
		}
		
		this.download(request, response, sId);
	}

	/**
	 * 文件下载
	 * 注意:为内部请求
	 * @param request
	 * @param response
	 * @param sId 文件编号
	 */
	@ApiOperation(value="文件下载", notes="文件下载,注意:为内部请求")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sId", value="文件记录编号", dataType="String", paramType="query", required=true)
	})
	@ApiResponses({
		@ApiResponse(code=200, message="成功下载到文件|{\"success\": 布尔值, \"msg\": 文字提示, \"data\": 码值}"),
		@ApiResponse(code=400, message="错误的请求,请检查路径"),
		@ApiResponse(code=404, message="请求路径没有或页面跳转路径不对"),
		@ApiResponse(code=1000001, message="内部请求密钥错误"),
		@ApiResponse(code=1000002, message="您还没有登录或登录已超时,需要重新登录"),
		@ApiResponse(code=1000003, message="检查登录状态失败,请稍后重试！"),
		@ApiResponse(code=1000004, message="请求的操作不存在,请检查访问地址正确性，如大小写"),
		@ApiResponse(code=1000005, message="响应后在系统内部发生不可预知的错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=1019000, message="1019000~1999999为拦截器调用方法错误"),
		@ApiResponse(code=8001, message="记录编号不能为空"),
		@ApiResponse(code=7101, message="文件信息数据不存在"),
		@ApiResponse(code=7103, message="文件信息查询失败，发生异常"),
		@ApiResponse(code=9001, message="文件信息记录中缺失文件路径")
	})
	@RequestMapping(method=RequestMethod.GET, value="/download/inside")
	public void download(HttpServletRequest request,
			HttpServletResponse response, String sId) {
		MsgEmity me = fileCabinetService.findById(sId);
		if (!me.isSuccess()) {
			HttpServletUtil.setTxt(response, me);
			return;
		}
		
		FileCabinet fileCabinet = me.getData();
		String sPath = fileCabinet.getsPath();
		String sName = fileCabinet.getsName();
		
		if (null == sPath || "".equals(sPath)) {
			HttpServletUtil.setTxt(response, MsgEmity.err(9001, "文件信息记录中缺失文件路径"));
			return;
		}
		
		if (null != sName && !"".equals(sName)) {
			HttpServletUtil.downloadFile(request, response, sPath, sName);
			return;
		}
		
		HttpServletUtil.downloadFile(request, response, sPath, null);
	}

	/**
	 * 判断文件是否存在
	 * @param sRecordId 记录编号
	 * @return
	 */
	@ApiOperation(value="判断文件是否存在")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sRecordId", value="记录编号", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method=RequestMethod.GET, value="/check")
	public MsgEmity checkFileExist(String sRecordId) {
		return fileCabinetService.checkFileExist(sRecordId);
	}

	/**
	 * 创建上传文件验证密钥
	 * @param person 操作人
	 * @param project 项目名
	 * @param requestDate 请求时间
	 * @param disturbStr 干扰串
	 * @return
	 */
	@ApiOperation(value="创建上传文件验证密钥", notes="由请求参数的 操作人、项目名、请求时间、干扰串通过';'串联后进行MD5操作得到")
	@ApiImplicitParams({
		@ApiImplicitParam(name="person", value="操作人", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="project", value="项目名", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="requestDate", value="请求时间", dataType="String", paramType="query", defaultValue="2020-05-02 13:06:04", example="2020-05-01 13:05:01", required=true),
		@ApiImplicitParam(name="disturbStr", value="干扰串", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.GET}, value="/create/key/up")
	public MsgEmity createCheckKey(String person, String project, String requestDate, String disturbStr) {
		MsgEmity me = ValidDataUtil.createQueryKey(requestDate, disturbStr, person, project);
		if (!me.isSuccess()) {
			return me;
		}
		
		return new MsgEmity(true, "创建上传文件验证密钥成功", me.getData());
	}

	/**
	 * 创建下载文件验证密钥
	 * @param sId 文件编号
	 * @param requestDate 请求时间
	 * @param disturbStr 干扰串
	 * @return
	 */
	@ApiOperation(value="创建下载文件验证密钥", notes="由请求参数的 文件编号、请求时间、干扰串一起通过';'串联后进行MD5操作得到")
	@ApiImplicitParams({
		@ApiImplicitParam(name="sId", value="文件编号", dataType="String", paramType="query", required=true),
		@ApiImplicitParam(name="requestDate", value="请求时间", dataType="String", paramType="query", defaultValue="2020-05-02 13:06:04", example="2020-05-01 13:05:01", required=true),
		@ApiImplicitParam(name="disturbStr", value="干扰串", dataType="String", paramType="query", required=true)
	})
	@RequestMapping(method={RequestMethod.GET}, value="/create/key/down")
	public MsgEmity createCheckKey(String sId, String requestDate, String disturbStr) {
		MsgEmity me = ValidDataUtil.createQueryKey(requestDate, disturbStr, sId);
		if (!me.isSuccess()) {
			return me;
		}
		
		return new MsgEmity(true, "创建下载文件验证密钥成功", me.getData());
	}

}
